﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Drawing.Imaging;
using System.Diagnostics;
using KAImage;

namespace IPCPhotoEditor
{
    public enum ImagesBrowseMode : int
    {
        SingleFile = 0,
        Directory = 1,
    }

    public partial class ImageBrowser : UserControl
    {
        private ImagesBrowseMode _mode = ImagesBrowseMode.Directory;
        public ImagesBrowseMode BrowseMode
        {
            set 
            {
                _mode = value;
                bool visible = (_mode == ImagesBrowseMode.Directory);
                buttonBack.Visible = visible;
                buttonNext.Visible = visible;
                textBoxIndex.Visible = visible;
                label1.Visible = visible;
                labelTotal.Visible = visible; 
            }
            get
            {
                return _mode;
            }
        }

        private string directoryPath = "";

        private Bitmap _sourceImage = null;

        private Bitmap _workImage = null;

        private Bitmap _showImage = null;

        private List<FileInfo> listFiles = new List<FileInfo>();

        private int _currentIndex = 0;

        private string FileDescription = "";

        private bool _bIndexEditActived = false;

        private bool _bWorkingUpdated = false;
 
        public Bitmap WorkImage
        {
            get 
            {
                if (_workImage != null)
                {
                    return _workImage;
                }
                return null;
            }
        }

        public bool HasImage
        {
            get
            {
                return pictureBoxSRC.Image != null && _sourceImage != null;
            }
        }

        public BrowseFileInfoReportedEventHandler BrowseFileInfoReported = null;

        private void OnBrowseFileInfoUpdated(string info, string name)
        {
            if (BrowseFileInfoReported != null)
            {
                BrowseFileInfoReported(this, new BrowseFileInfoReportedEventArgs(info, name));
            }
        }

        public BrowsedImageUpdatedEventHandler BrowsedImageUpdated = null;

        private void OnBrowsedImageUpdated(Bitmap bmp)
        {
            if (BrowsedImageUpdated != null)
            {
                BrowsedImageUpdated(this, new BrowsedImageUpdatedEventArgs(bmp));
            }
        }

        public int CurrentIndex
        {
            get { return _currentIndex; }
        }

        public ImageBrowser()
        {
            InitializeComponent();
        }

        public void SaveAsNewImage(string fileName)
        {
            ImageFormat format = ImageAdjustments.GetImageFormat(fileName);
            _workImage.Save(fileName, format);
        }   

        public void ResetImage()
        {
            if (_bWorkingUpdated)
            {
                _bWorkingUpdated = false;
                DisposeWorkingImage();
                _workImage = _sourceImage.Clone() as Bitmap;
                _showImage = _sourceImage.Clone() as Bitmap;
                pictureBoxSRC.Image = _showImage;
                OnBrowsedImageUpdated(_workImage);
            }        
        }

        public void WorkImage_Updated(object sender, WorkImageUpdatedEventArgs e)
        {
            _bWorkingUpdated = true;
            DisposeWorkingImage();
            _workImage = e.NewImage;
            _showImage = _workImage.Clone() as Bitmap;
            pictureBoxSRC.Image = _showImage;

          
            OnBrowsedImageUpdated(_workImage);
          
        }

        public void UpdateWorkImage()
        {
            _bWorkingUpdated = true;
            pictureBoxSRC.Image = null;
            if (_showImage != null)
            {
                _showImage.Dispose();
                _showImage = null;
            }
            _showImage = _workImage.Clone() as Bitmap;
            pictureBoxSRC.Image = _showImage;
            OnBrowsedImageUpdated(_workImage);
        }

        public void SetPageButtonEnabled(bool enabled)
        {
            buttonBack.Enabled = enabled;
            buttonNext.Enabled = enabled;
            if (enabled)
            {
                UpdateCtrls();
            }           
        }

        private void UpdateImage(int index)
        {
            _bWorkingUpdated = false;
            if (listFiles.Count == 0)
            {
                UpdateCtrls();
                return;
            }
            _currentIndex = index;
            LoadImage();
            UpdateCtrls();
        }

        public void SetSingleImage(string sourceFile)
        {
            listFiles.Clear();
            BrowseMode = ImagesBrowseMode.SingleFile;
            _currentIndex = -1;
            FileDescription = "";
            _bWorkingUpdated = false;
            LoadImage(sourceFile);
        }

        public void SetDirectory(string newDirectory)
        {
            listFiles.Clear();
            DisposeImage();
            BrowseMode = ImagesBrowseMode.Directory;
            _currentIndex = -1;
            FileDescription = "";
            _bWorkingUpdated = false;
            directoryPath = newDirectory;
            if (GetFiles())
            {
                if (listFiles.Count == 0)
                {
                    UpdateCtrls();
                    return;
                }
                UpdateImage(listFiles.Count - 1);
            }
            else 
            {
                //MessageBox.Show("无效的路径(目录不存在): " + directoryPath);
                SetSingleImage("D://Photos//20181126154348_2.png");
            }
        }

        private void DisposeWorkingImage()
        {
            pictureBoxSRC.Image = null;      
            if (_showImage != null)
            {
                _showImage.Dispose();
                _showImage = null;
            }
            if (_workImage != null)
            {
                _workImage.Dispose();
                _workImage = null;
            }
        }

        private void DisposeImage()
        {
            pictureBoxSRC.Image = null;
            if (_sourceImage != null)
            {
                _sourceImage.Dispose();
                _sourceImage = null;
            }
            if (_showImage != null)
            {
                _showImage.Dispose();
                _showImage = null;
            }
            if (_workImage != null)
            {
                _workImage.Dispose();
                _workImage = null;
            }
        }

        private bool GetFiles()
        {
            listFiles.Clear();
            if (!Directory.Exists(directoryPath))
            {
                return false;
            }
            DirectoryInfo di = new DirectoryInfo(directoryPath);
            FileInfo[] files = di.GetFiles();
            string fileName;
            for (int i = 0; i < files.Length; i++)
            {
                fileName = files[i].Name.ToLower();
                if (fileName.EndsWith(".png") || fileName.EndsWith(".jpg") || fileName.EndsWith(".bmp"))
                {
                    listFiles.Add(files[i]);
                }
            }
            listFiles.Sort((x, y) => x.LastWriteTime.CompareTo(y.LastWriteTime));
            labelTotal.Text = listFiles.Count.ToString();
            return true;
        }

        private void UpdateCtrls()
        {
            if (listFiles.Count == 0)
            {
                _currentIndex = 0;
                textBoxIndex.Text = "0";
                labelTotal.Text = "0";
                buttonNext.Enabled = false;
                buttonBack.Enabled = false;
                return;
            }               
            if (listFiles.Count == 1)
            {
                buttonNext.Enabled = false;
                buttonBack.Enabled = false;
            }
            else if (_currentIndex == listFiles.Count - 1)
            {
                buttonNext.Enabled = false;
                buttonBack.Enabled = true;
            }
            else if (_currentIndex == 0)
            {
                buttonNext.Enabled = true;
                buttonBack.Enabled = false;
            }
            else
            {
                buttonNext.Enabled = true;
                buttonBack.Enabled = true;
            }
            textBoxIndex.Text = (_currentIndex+1).ToString();
        }

        private string FileSize(FileInfo fileInfo)
        {
            if(fileInfo.Length < 102400)
            {
               double size = Math.Round(fileInfo.Length / 1024.0, 1);
               return size.ToString() + " KB";
            }
            else
            {
                double size = Math.Round(fileInfo.Length / 1024576.0, 2);
                return size.ToString() + " MB";
            }
        }

        private bool LoadImage()
        {
            if (listFiles.Count == 0)
            {
                return true;
            }
            if (_currentIndex >= listFiles.Count)
            {
                MessageBox.Show("索引错误，图像加载失败!");
                return false;
            }
            string fileName = listFiles[_currentIndex].FullName;
            return LoadImage(fileName);
        }

        private bool LoadImage(string fileName)
        {                    
            if (!File.Exists(fileName))
            {
                MessageBox.Show("图像不存在!");
                return false;
            }
            try
            {
                _sourceImage = new Bitmap(fileName);
                _showImage = _sourceImage.Clone() as Bitmap;
                _workImage = _sourceImage.Clone() as Bitmap;
                pictureBoxSRC.Image = _showImage;
                FileInfo file;
                if (_mode == ImagesBrowseMode.Directory)
                {
                    file = listFiles[_currentIndex];
                }
                else
                {
                    file = new FileInfo(fileName);
                }
                FileDescription = string.Format("{0}, 大小{1}, 创建时间:{2}", 
                    file.FullName, 
                    FileSize(file), 
                    file.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss.fff"));
                OnBrowseFileInfoUpdated(FileDescription, Path.GetFileNameWithoutExtension(file.FullName));
                OnBrowsedImageUpdated(_workImage);
                return true;
            }
            catch (Exception ex)
            {
                DisposeImage();
                MessageBox.Show("图像加载错误: " + ex.Message);
                return false;
            }
        }

        private void buttonBack_Click(object sender, EventArgs e)
        {
            if (_currentIndex == 0)
            {
                return;
            }
            buttonBack.Enabled = false;
            _currentIndex--;
            UpdateCurrentImage();
        }

        private void UpdateCurrentImage()
        {
            DisposeImage();
            UpdateImage(_currentIndex);
        }

        private void buttonNext_Click(object sender, EventArgs e)
        {
            if (_currentIndex == listFiles.Count - 1)
            {
                return;
            }
            buttonNext.Enabled = false;
            _currentIndex++;
            UpdateCurrentImage();
        }

        private void textBoxIndex_Validating(object sender, CancelEventArgs e)
        {
            int val;
            if (int.TryParse(textBoxIndex.Text, out val))
            {
                if (val < 0)
                {
                    e.Cancel = true;
                }
                else if (val > listFiles.Count)
                {
                    e.Cancel = true;
                }
                else
                {
                    _currentIndex = val - 1;
                    UpdateCurrentImage();
                }
            }
            else
            {
                textBoxIndex.Focus();
               // e.Cancel = true;
            }
        }

        private void textBoxIndex_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == '\b'
               || Char.IsDigit(e.KeyChar)
               || Char.IsControl(e.KeyChar)
               || e.KeyChar == 46)
            {
                e.Handled = false;
            }
            else
            {
                e.Handled = true;
            }
        }

        private void textBoxIndex_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            _bIndexEditActived = !_bIndexEditActived;
            textBoxIndex.ReadOnly = !_bIndexEditActived;
            if (_bIndexEditActived)
            {
                textBoxIndex.Focus();
                textBoxIndex.Select(0, 0);
            }
        }

        private void textBoxIndex_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                labelTotal.Focus();
            }
        }
    }
}
